# code to load packages
library(tidyverse)
library(tidymodels)
library(knitr)
library(dplyr)
library(ggplot2)
library(patchwork)
library(corrplot)
corrplot 0.94 loaded
#baseR
auto <- read_csv("data/autopod_data.csv")
New names:
• `notes` -> `notes...22`
• `notes` -> `notes...60`
• `` -> `...98`
Rows: 582 Columns: 122
── Column specification ─────────────────────────────────────────────────────────
Delimiter: ","
chr (108): Collector, Higher taxon, Taxon, miss mC, miss mT, miss man-D, mis...
dbl (2): radius L, Ulna L
lgl (12): m2-5 av, hpp2-5 av, hmp2-5 av, hdp2-5 av, notes...60, fpp2-5 av, f...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#Set hms as numeric
auto$hm1 <- as.numeric(as.character(auto$hm1))
Warning: NAs introduced by coercion
auto$hm2 <- as.numeric(as.character(auto$hm2))
Warning: NAs introduced by coercion
auto$hm3 <- as.numeric(as.character(auto$hm3))
Warning: NAs introduced by coercion
auto$hm4 <- as.numeric(as.character(auto$hm4))
Warning: NAs introduced by coercion
auto$hm5 <- as.numeric(as.character(auto$hm5))
Warning: NAs introduced by coercion
#Set hpps as numeric
auto$hpp1 <- as.numeric(as.character(auto$hpp1))
Warning: NAs introduced by coercion
auto$hpp2 <- as.numeric(as.character(auto$hpp2))
Warning: NAs introduced by coercion
auto$hpp3 <- as.numeric(as.character(auto$hpp3))
Warning: NAs introduced by coercion
auto$hpp4 <- as.numeric(as.character(auto$hpp4))
Warning: NAs introduced by coercion
auto$hpp5 <- as.numeric(as.character(auto$hpp5))
Warning: NAs introduced by coercion
#remove NAs
autoclean <- auto %>%
filter(complete.cases(hm1, hm2, hm3, hm4, hm5, hpp1, hpp2, hpp3, hpp4, hpp5))
#avg hand metatarsals for each higher taxa
hm_avg <- autoclean |>
group_by(`Higher taxon`) |>
summarize(average_hm1 = mean(hm1, na.rm = TRUE),
average_hm2 = mean(hm2, na.rm = TRUE),
average_hm3 = mean(hm3, na.rm = TRUE),
average_hm4 = mean(hm4, na.rm = TRUE),
average_hm5 = mean(hm5, na.rm = TRUE)
)
print(hm_avg)
#avg proximal phalanges for each higher taxa
hpp_avg <- autoclean |>
group_by(`Higher taxon`) |>
summarize(average_hpp1 = mean(hpp1, na.rm = TRUE),
average_hpp2 = mean(hpp2, na.rm = TRUE),
average_hpp3 = mean(hpp3, na.rm = TRUE),
average_hpp4 = mean(hpp4, na.rm = TRUE),
average_hpp5 = mean(hpp5, na.rm = TRUE)
)
print(hpp_avg)
#get total digit lengths
autoclean$total_digit1 <- autoclean$hm1 + autoclean$hpp1
autoclean$total_digit2 <- autoclean$hm2 + autoclean$hpp2
autoclean$total_digit3 <- autoclean$hm3 + autoclean$hpp3
autoclean$total_digit4 <- autoclean$hm4 + autoclean$hpp4
autoclean$total_digit5 <- autoclean$hm5 + autoclean$hpp5
head(autoclean)
NA
#AVG DIGIT LENGTHS
avg_digit_lengths <- hm_avg |>
full_join(hpp_avg, by = "Higher taxon") |>
mutate(
avg_digit1 = hm_avg$average_hm1 + hpp_avg$average_hpp1,
avg_digit2 = hm_avg$average_hm2 + hpp_avg$average_hpp2,
avg_digit3 = hm_avg$average_hm3 + hpp_avg$average_hpp3,
avg_digit4 = hm_avg$average_hm4 + hpp_avg$average_hpp4,
avg_digit5 = hm_avg$average_hm5 + hpp_avg$average_hpp5
) |>
select(`Higher taxon`, avg_digit1, avg_digit2, avg_digit3, avg_digit4, avg_digit5)
avg_digit_lengths
#EXPLORING COVARIATION
# biplots for comparing digit lengths
#to calc rsquared
r_squared <- function(x, y) {
model <- lm(y ~ x)
summary(model)$r.squared
}
pairs <- list(
c("total_digit1", "total_digit2"),
c("total_digit1", "total_digit3"),
c("total_digit1", "total_digit4"),
c("total_digit1", "total_digit5"),
c("total_digit2", "total_digit3"),
c("total_digit2", "total_digit4"),
c("total_digit2", "total_digit5"),
c("total_digit3", "total_digit4"),
c("total_digit3", "total_digit5"),
c("total_digit4", "total_digit5")
)
for (pair in pairs) {
x <- autoclean[[pair[1]]]
y <- autoclean[[pair[2]]]
r_squared <- calculate_r_squared(x, y)
p <- ggplot(autoclean, aes_string(x = pair[1], y = pair[2])) +
geom_point() +
labs(x = pair[1], y = pair[2], title = paste("Biplot of", pair[1], "and", pair[2]), subtitle = paste("R^2 =", r_squared)) +
theme_minimal()
print(p)
}










#correlation matrix for total digit lengths
correlation_matrix <- cor(autoclean[, c("total_digit1", "total_digit2", "total_digit3", "total_digit4", "total_digit5")])
print(correlation_matrix)
total_digit1 total_digit2 total_digit3 total_digit4 total_digit5
total_digit1 1.0000000 0.9566183 0.9565192 0.9634344 0.9664044
total_digit2 0.9566183 1.0000000 0.9791062 0.9725032 0.9686648
total_digit3 0.9565192 0.9791062 1.0000000 0.9941848 0.9786560
total_digit4 0.9634344 0.9725032 0.9941848 1.0000000 0.9928006
total_digit5 0.9664044 0.9686648 0.9786560 0.9928006 1.0000000
corrplot(correlation_matrix, method = "color", addCoef.col = "black", tl.col = "black", tl.srt = 45)

# Function to calculate R^2
calc_r_squared <- function(x, y) {
model <- lm(y ~ x)
summary(model)$r.squared
}
# Create pairs of digit lengths
pairs <- list(
c("total_digit1", "total_digit2"),
c("total_digit1", "total_digit3"),
c("total_digit1", "total_digit4"),
c("total_digit1", "total_digit5"),
c("total_digit2", "total_digit3"),
c("total_digit2", "total_digit4"),
c("total_digit2", "total_digit5"),
c("total_digit3", "total_digit4"),
c("total_digit3", "total_digit5"),
c("total_digit4", "total_digit5")
)
# Get unique taxa
unique_taxa <- unique(autoclean$`Higher taxon`)
# for each higher taxa
for (taxon in unique_taxa) {
# filter for the current higher taxon
taxa_data <- autoclean[autoclean$`Higher taxon` == taxon, ]
# going thru each digit pair
for (pair in pairs) {
x <- taxa_data[[pair[1]]]
y <- taxa_data[[pair[2]]]
# get r^2
r_squared <- calc_r_squared(x, y)
# actual plot
p <- ggplot(taxa_data, aes_string(x = pair[1], y = pair[2])) +
geom_point(color = "#0096FF", alpha = 0.6, size = 3) +
labs(
x = pair[1],
y = pair[2],
title = paste("Biplot of", pair[1], "and", pair[2], "for", taxon),
subtitle = paste("R^2 =", round(r_squared, 3))
) +
theme_minimal() +
theme(
plot.title = element_text(size = 12, face = "bold", color = "#0096FF"),
plot.subtitle = element_text(size = 10, color = "black"),
axis.title.x = element_text(size = 10, face = "bold"),
axis.title.y = element_text(size = 10, face = "bold"),
panel.background = element_rect(fill = "#FFF1F3"),
panel.grid.major = element_line(color = "white"),
panel.grid.minor = element_line(color = "white")
)
print(p)
}
}






































































unique_taxa <- unique(autoclean$`Higher taxon`)
for (taxon in unique_taxa) {
taxa_data <- autoclean[autoclean$`Higher taxon` == taxon, ]
correlation_matrix <- cor(autoclean[, c("total_digit1", "total_digit2",
"total_digit3", "total_digit4",
"total_digit5")])
print(taxon)
print(correlation_matrix)
corrplot(correlation_matrix, method = "color", addCoef.col = "black", tl.col =
"black", tl.srt = 45, title=taxon, mar=c(0,0,1,0) )
}
[1] "Hominoidea"
total_digit1 total_digit2 total_digit3 total_digit4 total_digit5
total_digit1 1.0000000 0.9566183 0.9565192 0.9634344 0.9664044
total_digit2 0.9566183 1.0000000 0.9791062 0.9725032 0.9686648
total_digit3 0.9565192 0.9791062 1.0000000 0.9941848 0.9786560
total_digit4 0.9634344 0.9725032 0.9941848 1.0000000 0.9928006
total_digit5 0.9664044 0.9686648 0.9786560 0.9928006 1.0000000
[1] "Cercopithecoidea"
total_digit1 total_digit2 total_digit3 total_digit4 total_digit5
total_digit1 1.0000000 0.9566183 0.9565192 0.9634344 0.9664044
total_digit2 0.9566183 1.0000000 0.9791062 0.9725032 0.9686648
total_digit3 0.9565192 0.9791062 1.0000000 0.9941848 0.9786560
total_digit4 0.9634344 0.9725032 0.9941848 1.0000000 0.9928006
total_digit5 0.9664044 0.9686648 0.9786560 0.9928006 1.0000000

[1] "Dermoptera"
total_digit1 total_digit2 total_digit3 total_digit4 total_digit5
total_digit1 1.0000000 0.9566183 0.9565192 0.9634344 0.9664044
total_digit2 0.9566183 1.0000000 0.9791062 0.9725032 0.9686648
total_digit3 0.9565192 0.9791062 1.0000000 0.9941848 0.9786560
total_digit4 0.9634344 0.9725032 0.9941848 1.0000000 0.9928006
total_digit5 0.9664044 0.9686648 0.9786560 0.9928006 1.0000000

[1] "Platyrrhini"
total_digit1 total_digit2 total_digit3 total_digit4 total_digit5
total_digit1 1.0000000 0.9566183 0.9565192 0.9634344 0.9664044
total_digit2 0.9566183 1.0000000 0.9791062 0.9725032 0.9686648
total_digit3 0.9565192 0.9791062 1.0000000 0.9941848 0.9786560
total_digit4 0.9634344 0.9725032 0.9941848 1.0000000 0.9928006
total_digit5 0.9664044 0.9686648 0.9786560 0.9928006 1.0000000

[1] "Scandentia"
total_digit1 total_digit2 total_digit3 total_digit4 total_digit5
total_digit1 1.0000000 0.9566183 0.9565192 0.9634344 0.9664044
total_digit2 0.9566183 1.0000000 0.9791062 0.9725032 0.9686648
total_digit3 0.9565192 0.9791062 1.0000000 0.9941848 0.9786560
total_digit4 0.9634344 0.9725032 0.9941848 1.0000000 0.9928006
total_digit5 0.9664044 0.9686648 0.9786560 0.9928006 1.0000000

[1] "Strepsirrhini"
total_digit1 total_digit2 total_digit3 total_digit4 total_digit5
total_digit1 1.0000000 0.9566183 0.9565192 0.9634344 0.9664044
total_digit2 0.9566183 1.0000000 0.9791062 0.9725032 0.9686648
total_digit3 0.9565192 0.9791062 1.0000000 0.9941848 0.9786560
total_digit4 0.9634344 0.9725032 0.9941848 1.0000000 0.9928006
total_digit5 0.9664044 0.9686648 0.9786560 0.9928006 1.0000000

[1] "Tarsiiforms"
total_digit1 total_digit2 total_digit3 total_digit4 total_digit5
total_digit1 1.0000000 0.9566183 0.9565192 0.9634344 0.9664044
total_digit2 0.9566183 1.0000000 0.9791062 0.9725032 0.9686648
total_digit3 0.9565192 0.9791062 1.0000000 0.9941848 0.9786560
total_digit4 0.9634344 0.9725032 0.9941848 1.0000000 0.9928006
total_digit5 0.9664044 0.9686648 0.9786560 0.9928006 1.0000000


LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CiMgY29kZSB0byBsb2FkIHBhY2thZ2VzCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRpZHltb2RlbHMpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoY29ycnBsb3QpCgojYmFzZVIKYGBgCgpgYGB7cn0KYXV0byA8LSByZWFkX2NzdigiZGF0YS9hdXRvcG9kX2RhdGEuY3N2IikKCiNTZXQgaG1zIGFzIG51bWVyaWMgCmF1dG8kaG0xIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGF1dG8kaG0xKSkKYXV0byRobTIgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoYXV0byRobTIpKQphdXRvJGhtMyA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihhdXRvJGhtMykpCmF1dG8kaG00IDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGF1dG8kaG00KSkKYXV0byRobTUgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoYXV0byRobTUpKQoKI1NldCBocHBzIGFzIG51bWVyaWMgCmF1dG8kaHBwMSA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihhdXRvJGhwcDEpKQphdXRvJGhwcDIgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoYXV0byRocHAyKSkKYXV0byRocHAzIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGF1dG8kaHBwMykpCmF1dG8kaHBwNCA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihhdXRvJGhwcDQpKQphdXRvJGhwcDUgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoYXV0byRocHA1KSkKYGBgCgoKYGBge3J9CiNyZW1vdmUgTkFzCmF1dG9jbGVhbiA8LSBhdXRvICU+JQogIGZpbHRlcihjb21wbGV0ZS5jYXNlcyhobTEsIGhtMiwgaG0zLCBobTQsIGhtNSwgaHBwMSwgaHBwMiwgaHBwMywgaHBwNCwgaHBwNSkpCgpgYGAKCmBgYHtyfQojYXZnIGhhbmQgbWV0YXRhcnNhbHMgZm9yIGVhY2ggaGlnaGVyIHRheGEKCmhtX2F2ZyA8LSBhdXRvY2xlYW4gfD4KICBncm91cF9ieShgSGlnaGVyIHRheG9uYCkgfD4KICBzdW1tYXJpemUoYXZlcmFnZV9obTEgPSBtZWFuKGhtMSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgYXZlcmFnZV9obTIgPSBtZWFuKGhtMiwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgYXZlcmFnZV9obTMgPSBtZWFuKGhtMywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgYXZlcmFnZV9obTQgPSBtZWFuKGhtNCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgYXZlcmFnZV9obTUgPSBtZWFuKGhtNSwgbmEucm0gPSBUUlVFKQogICAgICAgICAgICApCnByaW50KGhtX2F2ZykKYGBgCmBgYHtyfQojYXZnIHByb3hpbWFsIHBoYWxhbmdlcyBmb3IgZWFjaCBoaWdoZXIgdGF4YQoKaHBwX2F2ZyA8LSBhdXRvY2xlYW4gfD4KICBncm91cF9ieShgSGlnaGVyIHRheG9uYCkgfD4KICBzdW1tYXJpemUoYXZlcmFnZV9ocHAxID0gbWVhbihocHAxLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBhdmVyYWdlX2hwcDIgPSBtZWFuKGhwcDIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIGF2ZXJhZ2VfaHBwMyA9IG1lYW4oaHBwMywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgYXZlcmFnZV9ocHA0ID0gbWVhbihocHA0LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBhdmVyYWdlX2hwcDUgPSBtZWFuKGhwcDUsIG5hLnJtID0gVFJVRSkKICAgICAgICAgICAgKQpwcmludChocHBfYXZnKQpgYGAKCmBgYHtyfQojZ2V0IHRvdGFsIGRpZ2l0IGxlbmd0aHMgCgphdXRvY2xlYW4kdG90YWxfZGlnaXQxIDwtIGF1dG9jbGVhbiRobTEgKyBhdXRvY2xlYW4kaHBwMQphdXRvY2xlYW4kdG90YWxfZGlnaXQyIDwtIGF1dG9jbGVhbiRobTIgKyBhdXRvY2xlYW4kaHBwMgphdXRvY2xlYW4kdG90YWxfZGlnaXQzIDwtIGF1dG9jbGVhbiRobTMgKyBhdXRvY2xlYW4kaHBwMwphdXRvY2xlYW4kdG90YWxfZGlnaXQ0IDwtIGF1dG9jbGVhbiRobTQgKyBhdXRvY2xlYW4kaHBwNAphdXRvY2xlYW4kdG90YWxfZGlnaXQ1IDwtIGF1dG9jbGVhbiRobTUgKyBhdXRvY2xlYW4kaHBwNQoKaGVhZChhdXRvY2xlYW4pCgpgYGAKYGBge3J9CiNBVkcgRElHSVQgTEVOR1RIUwoKYXZnX2RpZ2l0X2xlbmd0aHMgPC0gaG1fYXZnIHw+CiAgZnVsbF9qb2luKGhwcF9hdmcsIGJ5ID0gIkhpZ2hlciB0YXhvbiIpIHw+CgogIG11dGF0ZSgKICAgICAgYXZnX2RpZ2l0MSA9IGhtX2F2ZyRhdmVyYWdlX2htMSArIGhwcF9hdmckYXZlcmFnZV9ocHAxLAogICAgYXZnX2RpZ2l0MiA9IGhtX2F2ZyRhdmVyYWdlX2htMiArIGhwcF9hdmckYXZlcmFnZV9ocHAyLAogICAgYXZnX2RpZ2l0MyA9IGhtX2F2ZyRhdmVyYWdlX2htMyArIGhwcF9hdmckYXZlcmFnZV9ocHAzLAogICAgYXZnX2RpZ2l0NCA9IGhtX2F2ZyRhdmVyYWdlX2htNCArIGhwcF9hdmckYXZlcmFnZV9ocHA0LAogICAgYXZnX2RpZ2l0NSA9IGhtX2F2ZyRhdmVyYWdlX2htNSArIGhwcF9hdmckYXZlcmFnZV9ocHA1CiAgICApIHw+CiAgICBzZWxlY3QoYEhpZ2hlciB0YXhvbmAsIGF2Z19kaWdpdDEsIGF2Z19kaWdpdDIsIGF2Z19kaWdpdDMsIGF2Z19kaWdpdDQsIGF2Z19kaWdpdDUpCgphdmdfZGlnaXRfbGVuZ3RocwpgYGAKCmBgYHtyfQojRVhQTE9SSU5HIENPVkFSSUFUSU9OCiMgQklQTE9UUyBGT1IgQUxMIERJR0lUUyBJTiBEQVRBU0VUIAoKI3RvIGNhbGMgcnNxdWFyZWQgCnJfc3F1YXJlZCA8LSBmdW5jdGlvbih4LCB5KSB7CiAgbW9kZWwgPC0gbG0oeSB+IHgpCiAgc3VtbWFyeShtb2RlbCkkci5zcXVhcmVkCn0KCnBhaXJzIDwtIGxpc3QoCiAgYygidG90YWxfZGlnaXQxIiwgInRvdGFsX2RpZ2l0MiIpLAogIGMoInRvdGFsX2RpZ2l0MSIsICJ0b3RhbF9kaWdpdDMiKSwKICBjKCJ0b3RhbF9kaWdpdDEiLCAidG90YWxfZGlnaXQ0IiksCiAgYygidG90YWxfZGlnaXQxIiwgInRvdGFsX2RpZ2l0NSIpLAogIGMoInRvdGFsX2RpZ2l0MiIsICJ0b3RhbF9kaWdpdDMiKSwKICBjKCJ0b3RhbF9kaWdpdDIiLCAidG90YWxfZGlnaXQ0IiksCiAgYygidG90YWxfZGlnaXQyIiwgInRvdGFsX2RpZ2l0NSIpLAogIGMoInRvdGFsX2RpZ2l0MyIsICJ0b3RhbF9kaWdpdDQiKSwKICBjKCJ0b3RhbF9kaWdpdDMiLCAidG90YWxfZGlnaXQ1IiksCiAgYygidG90YWxfZGlnaXQ0IiwgInRvdGFsX2RpZ2l0NSIpCikKCmZvciAocGFpciBpbiBwYWlycykgewogIHggPC0gYXV0b2NsZWFuW1twYWlyWzFdXV0KICB5IDwtIGF1dG9jbGVhbltbcGFpclsyXV1dCiAgcl9zcXVhcmVkIDwtIGNhbGN1bGF0ZV9yX3NxdWFyZWQoeCwgeSkKICBwIDwtIGdncGxvdChhdXRvY2xlYW4sIGFlc19zdHJpbmcoeCA9IHBhaXJbMV0sIHkgPSBwYWlyWzJdKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoeCA9IHBhaXJbMV0sIHkgPSBwYWlyWzJdLCB0aXRsZSA9IHBhc3RlKCJCaXBsb3Qgb2YiLCBwYWlyWzFdLCAiYW5kIiwgcGFpclsyXSksIHN1YnRpdGxlID0gcGFzdGUoIlJeMiA9Iiwgcl9zcXVhcmVkKSkgKwogICAgdGhlbWVfbWluaW1hbCgpCiAgcHJpbnQocCkKfQoKYGBgCmBgYHtyfQojQ09SUkVMQVRJT04gTUFUUklYIApjb3JyZWxhdGlvbl9tYXRyaXggPC0gY29yKGF1dG9jbGVhblssIGMoInRvdGFsX2RpZ2l0MSIsICJ0b3RhbF9kaWdpdDIiLCAidG90YWxfZGlnaXQzIiwgInRvdGFsX2RpZ2l0NCIsICJ0b3RhbF9kaWdpdDUiKV0pCnByaW50KGNvcnJlbGF0aW9uX21hdHJpeCkKCmNvcnJwbG90KGNvcnJlbGF0aW9uX21hdHJpeCwgbWV0aG9kID0gImNvbG9yIiwgYWRkQ29lZi5jb2wgPSAiYmxhY2siLCB0bC5jb2wgPSAiYmxhY2siLCB0bC5zcnQgPSA0NSkKYGBgCmBgYHtyfQoKIyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgUl4yCmNhbGNfcl9zcXVhcmVkIDwtIGZ1bmN0aW9uKHgsIHkpIHsKICBtb2RlbCA8LSBsbSh5IH4geCkKICBzdW1tYXJ5KG1vZGVsKSRyLnNxdWFyZWQKfQoKIyBDcmVhdGUgcGFpcnMgb2YgZGlnaXQgbGVuZ3RocwpwYWlycyA8LSBsaXN0KAogIGMoInRvdGFsX2RpZ2l0MSIsICJ0b3RhbF9kaWdpdDIiKSwKICBjKCJ0b3RhbF9kaWdpdDEiLCAidG90YWxfZGlnaXQzIiksCiAgYygidG90YWxfZGlnaXQxIiwgInRvdGFsX2RpZ2l0NCIpLAogIGMoInRvdGFsX2RpZ2l0MSIsICJ0b3RhbF9kaWdpdDUiKSwKICBjKCJ0b3RhbF9kaWdpdDIiLCAidG90YWxfZGlnaXQzIiksCiAgYygidG90YWxfZGlnaXQyIiwgInRvdGFsX2RpZ2l0NCIpLAogIGMoInRvdGFsX2RpZ2l0MiIsICJ0b3RhbF9kaWdpdDUiKSwKICBjKCJ0b3RhbF9kaWdpdDMiLCAidG90YWxfZGlnaXQ0IiksCiAgYygidG90YWxfZGlnaXQzIiwgInRvdGFsX2RpZ2l0NSIpLAogIGMoInRvdGFsX2RpZ2l0NCIsICJ0b3RhbF9kaWdpdDUiKQopCgojIEdldCB1bmlxdWUgdGF4YQp1bmlxdWVfdGF4YSA8LSB1bmlxdWUoYXV0b2NsZWFuJGBIaWdoZXIgdGF4b25gKQoKIyBmb3IgZWFjaCBoaWdoZXIgdGF4YSAKZm9yICh0YXhvbiBpbiB1bmlxdWVfdGF4YSkgewogICMgZmlsdGVyIGZvciB0aGUgY3VycmVudCBoaWdoZXIgdGF4b24KICB0YXhhX2RhdGEgPC0gYXV0b2NsZWFuW2F1dG9jbGVhbiRgSGlnaGVyIHRheG9uYCA9PSB0YXhvbiwgXQogIAogICMgZ29pbmcgdGhydSBlYWNoIGRpZ2l0IHBhaXIgCiAgZm9yIChwYWlyIGluIHBhaXJzKSB7CiAgICB4IDwtIHRheGFfZGF0YVtbcGFpclsxXV1dCiAgICB5IDwtIHRheGFfZGF0YVtbcGFpclsyXV1dCiAgICAKICAgICMgZ2V0IHJeMgogICAgcl9zcXVhcmVkIDwtIGNhbGNfcl9zcXVhcmVkKHgsIHkpCiAgICAKICAgICMgYWN0dWFsIHBsb3QKICAgIHAgPC0gZ2dwbG90KHRheGFfZGF0YSwgYWVzX3N0cmluZyh4ID0gcGFpclsxXSwgeSA9IHBhaXJbMl0pKSArCiAgICAgIGdlb21fcG9pbnQoY29sb3IgPSAiIzAwOTZGRiIsIGFscGhhID0gMC42LCBzaXplID0gMykgKwogICAgICBsYWJzKAogICAgICAgIHggPSBwYWlyWzFdLAogICAgICAgIHkgPSBwYWlyWzJdLAogICAgICAgIHRpdGxlID0gcGFzdGUoIkJpcGxvdCBvZiIsIHBhaXJbMV0sICJhbmQiLCBwYWlyWzJdLCAiZm9yIiwgdGF4b24pLAogICAgICAgIHN1YnRpdGxlID0gcGFzdGUoIlJeMiA9Iiwgcm91bmQocl9zcXVhcmVkLCAzKSkKICAgICAgKSArCiAgICAgIHRoZW1lX21pbmltYWwoKSArCiAgICAgIHRoZW1lKAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiLCBjb2xvciA9ICIjMDA5NkZGIiksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNGRkYxRjMiKSwgIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJ3aGl0ZSIpCiAgICAgICkKICAgIHByaW50KHApCiAgfQp9CgpgYGAKCmBgYHtyfQp1bmlxdWVfdGF4YSA8LSB1bmlxdWUoYXV0b2NsZWFuJGBIaWdoZXIgdGF4b25gKQoKZm9yICh0YXhvbiBpbiB1bmlxdWVfdGF4YSkgewogIHRheGFfZGF0YSA8LSBhdXRvY2xlYW5bYXV0b2NsZWFuJGBIaWdoZXIgdGF4b25gID09IHRheG9uLCBdCgogIGNvcnJlbGF0aW9uX21hdHJpeCA8LSBjb3IoYXV0b2NsZWFuWywgYygidG90YWxfZGlnaXQxIiwgInRvdGFsX2RpZ2l0MiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidG90YWxfZGlnaXQzIiwgInRvdGFsX2RpZ2l0NCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidG90YWxfZGlnaXQ1IildKQogIHByaW50KHRheG9uKQogIHByaW50KGNvcnJlbGF0aW9uX21hdHJpeCkKICBjb3JycGxvdChjb3JyZWxhdGlvbl9tYXRyaXgsIG1ldGhvZCA9ICJjb2xvciIsIGFkZENvZWYuY29sID0gImJsYWNrIiwgdGwuY29sID0gCiAgICAgICAgICAgICAiYmxhY2siLCB0bC5zcnQgPSA0NSwgICB0aXRsZT10YXhvbiwgICAgbWFyPWMoMCwwLDEsMCkgKQp9CmBgYApgYGB7cn0KCmBgYAoK